package com.tiancheng.trade.payment.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiancheng.trade.payment.channel.bo.StatisticsSubOrderRefundBo;
import com.tiancheng.trade.payment.enums.ChannelRefundTypeEnum;
import com.tiancheng.trade.payment.enums.FlowStatusEnum;
import com.tiancheng.trade.commom.core.enums.SettleStatusEnum;
import com.tiancheng.trade.payment.mapper.PaymentRefundFlowDetailMapper;
import com.tiancheng.trade.payment.model.PaymentRefundFlowDetail;
import com.tiancheng.trade.payment.service.PaymentRefundFlowDetailService;
import com.tiancheng.trade.payment.service.SettleMatchRefundService;
import com.tiancheng.trade.payment.util.ObjectConvertUtil;
import com.tiancheng.trade.payment.vo.admin.res.PaymentRefundFlowDetailResVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author kellen
 * @date 2021/2/19
 */
@Service
public class PaymentRefundFlowDetailServiceImpl implements PaymentRefundFlowDetailService {
    @Autowired
    private PaymentRefundFlowDetailMapper refundFlowDetailMapper;
    @Autowired
    private SettleMatchRefundService settleMatchRefundService;

    /**
     * 批量插入
     *
     * @param details {@link List<PaymentRefundFlowDetail>}
     * @return {@link Integer}
     */
    @Override
    public Integer saveBatch(List<PaymentRefundFlowDetail> details) {
        return refundFlowDetailMapper.saveBatch(details);
    }

    @Override
    public List<PaymentRefundFlowDetail> findByFlowId(String flowId) {
        if (StringUtils.isEmpty(flowId)) {
            return Collections.emptyList();
        }
        QueryWrapper<PaymentRefundFlowDetail> conditions = new QueryWrapper<>();
        conditions.eq("flow_id", flowId);
        return refundFlowDetailMapper.selectList(conditions);
    }

    @Override
    public List<PaymentRefundFlowDetailResVo> findSettleByFlowId(String flowId) {
        List<PaymentRefundFlowDetail> paymentRefundFlowDetails = this.findByFlowId(flowId);
        if (CollectionUtils.isEmpty(paymentRefundFlowDetails)) {
            return Collections.emptyList();
        }
        List<Map<String, Object>> settleDetails = settleMatchRefundService.findByRefundFlowIds(Collections.singletonList(flowId), SettleStatusEnum.SUCCESS.getCode());
        List<PaymentRefundFlowDetailResVo> result = new ArrayList<>();
        for (PaymentRefundFlowDetail paymentRefundFlowDetail : paymentRefundFlowDetails) {
            PaymentRefundFlowDetailResVo p = ObjectConvertUtil.convert(paymentRefundFlowDetail, PaymentRefundFlowDetailResVo.class).get();
            if (CollectionUtils.isEmpty(settleDetails)) {
                result.add(p);
                continue;
            }
            List<Map<String, Object>> subOrderSettleMatch = settleDetails.stream().filter(s -> s.get("refund_flow_id").toString().equals(paymentRefundFlowDetail.getFlowId())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(subOrderSettleMatch) || subOrderSettleMatch.get(0).get("update_time") == null) {
                result.add(p);
                continue;
            }
            LocalDateTime updateTime = Instant.ofEpochMilli(((Timestamp) subOrderSettleMatch.get(0).get("update_time")).getTime()).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
            p.setApprSuccessDate(updateTime);
            p.setApprId(subOrderSettleMatch.get(0).get("appr_id").toString());
            p.setApprId(subOrderSettleMatch.get(0).get("dist_id").toString());
            result.add(p);
        }
        return result;
    }

    @Override
    public Integer updateSettleBatch(Collection<Long> ids, HashMap<String, Object> colValMap) {
        return refundFlowDetailMapper.updateSettleBatch(ids, colValMap);
    }

    @Override
    public Integer updateRefundStatus(String flowId, String subOrderId, ChannelRefundTypeEnum refundType, FlowStatusEnum flowStatusEnum) {
        QueryWrapper<PaymentRefundFlowDetail> conditions = new QueryWrapper<>();
        conditions.eq("flow_id", flowId);
        if(refundType.getCode().equals(ChannelRefundTypeEnum.SPLIT.getCode())){
            Assert.isTrue(StringUtils.isNotEmpty(subOrderId), "未查询到相应退款流水");
            // 部分退款
            conditions.eq("sub_order_id", subOrderId);
        }
        PaymentRefundFlowDetail entity = new PaymentRefundFlowDetail();
        entity.setRefundStatus(flowStatusEnum.getCode());
        return refundFlowDetailMapper.update(entity,conditions);
    }

    @Override
    public PaymentRefundFlowDetail findBySubFlowId(String subFlowId) {
        QueryWrapper<PaymentRefundFlowDetail> conditions = new QueryWrapper<>();
        conditions.eq("sub_flow_id", subFlowId);
        return refundFlowDetailMapper.selectOne(conditions);
    }

    @Override
    public List<StatisticsSubOrderRefundBo> statisticsSubOrderRefund(List<String> subOrderIds) {
        if(CollectionUtils.isEmpty(subOrderIds)){
            return Collections.emptyList();
        }
        return refundFlowDetailMapper.statisticsSubOrderRefund(subOrderIds);
    }


    @Override
    public List<PaymentRefundFlowDetail> selectList(QueryWrapper<PaymentRefundFlowDetail> condition) {
        return refundFlowDetailMapper.selectList(condition);
    }
}
